package de.recipeminer.tools;

import com.db4o.ObjectSet;
import de.recipeminer.persistence.Db4oContainer;
import de.recipeminer.persistence.Db4oContainers;

import java.io.File;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
import java.util.Properties;
import java.util.SortedMap;
import java.util.UnknownFormatConversionException;

public class Tools {

    public static String getRubySourcePath() {
        return getMavenRubyPath("maven.sourceDir");
    }

    public static String getRubyTestSourcePath() {
        return getMavenRubyPath("maven.testSourceDir");
    }

    public static String getProjectBasePath() {
        Properties mavenProps = Config.getInstance().getMavenProperties();
        return mavenProps.getProperty("maven.baseDir");
    }

    protected static String getMavenRubyPath(String propKey) {
        Properties mavenProps = Config.getInstance().getMavenProperties();
        String rubySourcePath = mavenProps.getProperty(propKey).replaceFirst("java$", "ruby");
        File rubySource = new File(rubySourcePath);
        if (rubySource == null || !rubySource.exists()) 
        {
            throw new RuntimeException("Unable to find ruby source path!");
        }
        return rubySource.getAbsolutePath();
    }

    /**
     * Decodes chefkoch json string from charset coding ISO-8859-1 to UTF-8, as given in Config Class
     * performs some other preprocessing tasks using regular expressions.
     * @param ecs String to transcode
     * @return transcoded String
     */
    public static String transcodeChefkochString(String encoded_string) {

        //decode given string handling it as a ISO-8859-1 encoded string.
        String decoded_string = decodeStringFromCharset(encoded_string,Charset.forName(Config.chefkoch_charset_encoding_string));

        //delete all expressions like \n, \t, \r and others and...
        String cleaned_up_String = decoded_string.replaceAll("\\[a-z]", " ").
        //delete double white spaces
                replaceAll("\\s+", " ");

        return cleaned_up_String;
    }



        public static void assertUniqueInDatabase(Class class_) {
        Db4oContainer container = Db4oContainers.getDefault();
        ObjectSet result = container.query(class_);
        assert result.size() < 2;
    }

    /**
     * determines what Charset Decoding can be used to decipher a text, given by a sample.
     * @param a_cryptic_String like "Oliven\u0123l"
     *        what_it_should_like like "Olivenöl"
     * @return the correct charset
     * @throws UnknownFormatConversionException
     * @author Georg Mühlenberg
     * @exception If no correct decoding could be performed with the charsets supported by this jdk
     */
    public static Charset determineProperCharsetBySample(String a_cryptic_String, String what_it_should_look_like) throws UnknownFormatConversionException {
        String decodedString = "";
        Charset current_charset;

//all the keys of supported charsets are stored in an implicit map that Iterator li accesses on.
        Iterator li = Charset.availableCharsets().keySet().iterator();

//charset-WHILE
        while (li.hasNext()) {
            String charsetname = (String) li.next();
            current_charset = Charset.forName(charsetname);
            ByteBuffer bbuf = ByteBuffer.allocate(a_cryptic_String.getBytes().length);
            bbuf = de.recipeminer.tools.Tools.buffer(a_cryptic_String);

            decodedString = current_charset.decode(bbuf).toString();

            if (decodedString.equals(what_it_should_look_like)) {
                return current_charset;
            }

        }
//END of charset-test-WHILE

        throw new UnknownFormatConversionException("Proper Charset Could not be found.");
    }


    /**
     * Helping method to support implementation of other resources.
     * @param cs String to decode
     * @param charset Charset to use (e.g. Charset "ISO-8859-1" is returned by Charset.forname("ISO-8859-1") - statement.
     * See Charset API for detailed information.
     * @return decoded String
     */
    public static String decodeStringFromCharset(String cs, Charset charset) {
        //decode given string using the convenience method as implemented in Charset
        return charset.decode(buffer(cs)).toString();
    }


/**
 * Helping Method. Puts String into ByteBuffer
 */
    public static ByteBuffer buffer(String string) {
        byte[] bytes = string.getBytes();

        ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
        return (ByteBuffer) buffer.put(bytes).compact();
    }

/**
 * Helping Method. Gets String out of ByteBuffer
 */
    public static String string(ByteBuffer buffer) {
        if (buffer.hasArray()) {
            return new String(buffer.array());
        }
        return "";
    }
}
